home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / DIV / MM2LNKIO.I < prev    next >
Encoding:
Modula Implementation  |  1992-11-28  |  14.2 KB  |  501 lines

  1. IMPLEMENTATION MODULE MM2LnkIO;
  2. (*$R-*)
  3.  
  4. (*
  5.  * Ein-/Ausgabemodul für den Megamax Linker "MM2LINK"
  6.  *
  7.  * Dieses Modul wird vom Linker importiert und diese Implementation
  8.  * kann modifiziert werden, um das Ein-/Ausgabeformat zu verändern,
  9.  * beispielsweise für eine Commandline-Version des Linkers.
  10.  *
  11.  * Die vom Linker benutzten Prozeduren werden hier jeweils kurz
  12.  * bei der Deklaration beschrieben.
  13.  *
  14.  * ---------------------------------------------------------------------------
  15.  * 20.10.91  TT  Symbolausgabe implementiert, wird durch Option '-S' beim
  16.  *               Linker aktiviert.
  17.  * 28.11.92  TT  Ausgabe für Inititialisierungsliste (
  18.  *)
  19.  
  20. FROM SYSTEM IMPORT TSIZE;
  21. FROM TextWindows IMPORT ForceMode, WQualitySet, WindowQuality, Window,
  22.   ShowMode, Open;
  23. FROM ShellMsg IMPORT LLRange;
  24. FROM Files IMPORT GetStateMsg, State, Create, Access, ReplaceMode, Close, File;
  25. IMPORT Text, NumberIO;
  26. FROM FileNames IMPORT ConcatName;
  27. FROM Clock IMPORT CurrentTime, CurrentDate;
  28. FROM TimeConvert IMPORT TimeToText, DateToText;
  29. FROM PrgCtrl IMPORT TermProcess;
  30. FROM Storage IMPORT ALLOCATE;
  31. FROM Strings IMPORT String;
  32. IMPORT StrConv, Strings, MOSGlobals, TextWindows;
  33.  
  34.  
  35. CONST NameWidth = 20;
  36.       ColOffset = 2;
  37.       Columns = 15;
  38.       ErrLine = 20;
  39.       ProtLine = 20;
  40.       Stat0Line = 18;
  41.       Stat1Line = 18;
  42.       Stat2Line = 19;
  43.  
  44.  
  45. TYPE modNameDesc = RECORD
  46.                  row, col: CARDINAL;
  47.                  modname, filename: String;
  48.                END;
  49.  
  50. VAR stdOut: Window;
  51.     anotherMain, verbose: BOOLEAN;
  52.     highMod: CARDINAL;
  53.     currRow, currCol: CARDINAL;
  54.     Mod: POINTER TO ARRAY [1..MaxCard] OF modNameDesc;
  55.     linkerTitle: String;
  56.  
  57. (*
  58.  * Nicht exportierte Prozeduren
  59.  * ----------------------------
  60.  *)
  61.  
  62. PROCEDURE write (s: CHAR);
  63.  BEGIN
  64.    TextWindows.Write (stdOut, s)
  65.  END write;
  66.  
  67. PROCEDURE writeLn;
  68.  BEGIN
  69.    TextWindows.WriteLn (stdOut)
  70.  END writeLn;
  71.  
  72. PROCEDURE gotoXY (x,y: CARDINAL);
  73.   BEGIN
  74.     TextWindows.GotoXY (stdOut,x,y)
  75.   END gotoXY;
  76.  
  77. PROCEDURE delScr;
  78.   BEGIN
  79.     write(33C);
  80.     write ('E')
  81.   END delScr;
  82.  
  83. PROCEDURE delLine;
  84.   BEGIN
  85.     write(33C);
  86.     write('K')
  87.   END delLine;
  88.  
  89. PROCEDURE printCol (REF s0: ARRAY OF CHAR);
  90.   (* Modulnamen im Window anzeigen. 'currCol'/'currRow' geben Position an. *)
  91.   VAR s: String; ok: BOOLEAN;
  92.   BEGIN
  93.     Strings.Copy (s0,0,NameWidth-1,s,ok);
  94.     gotoXY (NameWidth*currCol, currRow+ColOffset);
  95.     WriteString (s);
  96.     INC (currRow);
  97.     IF currRow=Columns THEN
  98.       currRow:= 0; INC (currCol);
  99.     END
  100.   END printCol;
  101.  
  102. PROCEDURE clrCol (c,r:CARDINAL);
  103.   (* Modulnamen im Window löschen. *)
  104.   BEGIN
  105.     gotoXY (NameWidth*c, r+ColOffset);
  106.     WriteString (Strings.Space (NameWidth));
  107.   END clrCol;
  108.  
  109. PROCEDURE backCol;
  110.   (* Zeiger auf voriges Modul setzen und dies löschen. *)
  111.   BEGIN
  112.     IF currRow=0 THEN
  113.       currRow:=Columns-1;
  114.       DEC (currCol)
  115.     ELSE
  116.       DEC (currRow)
  117.     END;
  118.     clrCol (currCol, currRow);
  119.   END backCol;
  120.  
  121.  
  122. (*
  123.  * Für den Linker exportierte Prozeduren
  124.  * -------------------------------------
  125.  *)
  126.  
  127. PROCEDURE WriteString (REF s: ARRAY OF CHAR);
  128.  (* Schreibt Text an akt. Cursorposition, wird ggf. nach einer Report...-
  129.   * Prozedur aufgerufen, um weitere Informationen dazu auszugeben. *)
  130.  BEGIN
  131.    TextWindows.WriteString (stdOut, s)
  132.  END WriteString;
  133.  
  134. PROCEDURE ReadString (VAR s: ARRAY OF CHAR);
  135.  (* Wird nach Aufruf der Prompt-Funktion benutzt, um einen String einzulesen *)
  136.  BEGIN
  137.    TextWindows.ReadString (stdOut, s)
  138.  END ReadString;
  139.  
  140. PROCEDURE Read (VAR s: CHAR);
  141.  (* Wird nach Aufruf der Prompt-Funktion benutzt, um eine Taste einzulesen *)
  142.  BEGIN
  143.    TextWindows.Read (stdOut, s)
  144.  END Read;
  145.  
  146. PROCEDURE ClearEOP;
  147.   (* Aufruf jeweils nach Bestimmung von Output- und 1.Modulnamen *)
  148.   BEGIN
  149.     write (33C);
  150.     write ('J')
  151.   END ClearEOP;
  152.  
  153. PROCEDURE WriteMod (modNo: CARDINAL; REF modName, fileName: ARRAY OF CHAR);
  154.   (* Schreibt das Modul m. der Nr. 'modNo' auf den Bildschirm.
  155.    * 'modName': Modulname; 'fileName': Dateiname des zugehörigen IMP-Moduls *)
  156.   VAR ok: BOOLEAN;
  157.   BEGIN
  158.     IF modNo = 0 THEN HALT END;
  159.     IF anotherMain THEN
  160.       printCol ('--------');
  161.       anotherMain:= FALSE
  162.     END;
  163.     WITH Mod^[modNo] DO
  164.       row:= currRow; col:= currCol;
  165.       Strings.Assign (modName, modname, ok);
  166.       Strings.Assign (fileName, filename, ok);
  167.     END;
  168.     printCol (modName);
  169.     IF modNo > highMod THEN highMod:= modNo END;
  170.   END WriteMod;
  171.  
  172. PROCEDURE DiscardMods (downTo: CARDINAL);
  173.   (* Löscht alle Module vonm letzten bis zum angegebenen. Wird aufgerufenen,
  174.    * wenn eins der Module während der Ladephase fehlerhaft ist: es sollen
  175.    * dann alle seit des letzten Hauptmoduls geladenen Module wieder
  176.    * verschwinden. *)
  177.   BEGIN
  178.     WHILE highMod > downTo DO
  179.       backCol;
  180.       DEC (highMod)
  181.     END;
  182.   END DiscardMods;
  183.  
  184. PROCEDURE ClearMod (modNo: CARDINAL);
  185.   (* Löscht das angegebene Modul wieder. Wird aufgerufen, wenn das Modul
  186.    * durch Optimierung entfällt *)
  187.   BEGIN
  188.     WITH Mod^[modNo] DO
  189.       clrCol (col, row);
  190.     END;
  191.   END ClearMod;
  192.  
  193.  
  194. PROCEDURE ReportLinkError (REF mod, client, msg: ARRAY OF CHAR);
  195.   (* Aufruf bei Link-Fehlern. 'mod': betroffener Modulname; 'client': Name
  196.    * des Moduls, von dem 'mod' importiert wird; 'msg': Fehlertext. *)
  197.   VAR ch: CHAR;
  198.   BEGIN
  199.     gotoXY (0,ErrLine);
  200.     delLine;
  201.     IF client[0] # 0C THEN
  202.       WriteString ('>>> Importing '); WriteString (mod);
  203.       WriteString (' into '); WriteString (client)
  204.     ELSE
  205.       WriteString ('>>> Loading '); WriteString (mod);
  206.     END;
  207.     WriteString (': ');
  208.     WriteString (msg);
  209.     Read (ch);
  210.     gotoXY (0,ErrLine);
  211.     delLine;
  212.   END ReportLinkError;
  213.  
  214. PROCEDURE ReportIOError (ior: INTEGER);
  215.   (* Zeigt Dateifehler an. *)
  216.   VAR ch: CHAR; msg: ARRAY [0..31] OF CHAR;
  217.   BEGIN
  218.     gotoXY (0,ErrLine); delLine;
  219.     WriteString ('>>> I/O error: ');
  220.     GetStateMsg (ior,msg);
  221.     WriteString (msg);
  222.     Read (ch)
  223.   END ReportIOError;
  224.  
  225. PROCEDURE ReportError (REF s: ARRAY OF CHAR);
  226.   (* Zeigt allgemeine Fehler an, z.B. Speicherplatzmangel. *)
  227.   VAR ch: CHAR;
  228.   BEGIN
  229.     gotoXY (0,ErrLine); delLine;
  230.     WriteString ('>>> ');
  231.     WriteString (s);
  232.     Read (ch);
  233.   END ReportError;
  234.  
  235. PROCEDURE Report (n: CARDINAL; REF s: ARRAY OF CHAR);
  236.   (* Zeigt bestimmte Ereignisse/Vorgänge an, z.B. den Optimierungsvorgang. *)
  237.   BEGIN
  238.     IF (n = 1) & (highMod # 0) THEN
  239.       anotherMain:= TRUE;
  240.     END;
  241.     CASE n OF
  242.       0: |              (* Anzeige des Dateinamens der Ausgabedatei *)
  243.       1: n:= ProtLine | (* Ladephase: Anzeige d. augenblicklichen Hauptmoduls *)
  244.       2: n:= Stat0Line| (* unbenutzt *)
  245.       3: n:= ProtLine | (* Augenblicklicher Vorgang: Optimierung, Relozierung *)
  246.     END;
  247.     IF ~verbose THEN gotoXY (0,n); delLine; END;
  248.     WriteString (s);
  249.   END Report;
  250.  
  251. PROCEDURE Prompt (n: CARDINAL; REF s: ARRAY OF CHAR);
  252.   (* Eingabeaufforderung. Danach erfolgt Aufruf von 'Read' o. 'ReadString'. *)
  253.   BEGIN
  254.     CASE n OF
  255.       0: |              (* Frage nach Name f. Ausgabedatei *)
  256.       1: n:= ProtLine | (* Frage nach weiterem Hauptmodul *)
  257.       2: n:= Stat0Line| (* Frage nach Stack-Größe *)
  258.       3: n:= ProtLine | (* unbenutzt *)
  259.     END;
  260.     IF ~verbose THEN gotoXY (0,n); delLine; END;
  261.     WriteString (s)
  262.   END Prompt;
  263.  
  264. PROCEDURE ReportRealFormat (code: CARDINAL);
  265.   (* Anzeige des Real-Formats. 'code': 0: MM2-Reals, 1: ST-FPU, 2: TT-FPU *)
  266.   BEGIN
  267.     IF ~verbose THEN gotoXY (0, Stat1Line); END;
  268.     WriteString ('Real-Format: ');
  269.     IF code = 0 THEN
  270.       WriteString ('Megamax')
  271.     ELSE
  272.       WriteString ('IEEE (');
  273.       IF code = 1 THEN
  274.         WriteString ('ST-FPU)')
  275.       ELSE
  276.         WriteString ('TT-FPU)')
  277.       END
  278.     END;
  279.     IF verbose THEN writeLn END;
  280.   END ReportRealFormat;
  281.  
  282. PROCEDURE ReportCodeLen (text, bss, data: LONGCARD);
  283.   (* Anzeige der Längen von Code, Vars, Data-Segment *)
  284.   BEGIN
  285.     IF ~verbose THEN gotoXY (0,Stat2Line); END;
  286.     WriteString ('Length of Code: ');
  287.     WriteString (StrConv.CardToStr(text, 0));
  288.     WriteString ('    Length of BSS: ');
  289.     WriteString (StrConv.CardToStr(bss, 0));
  290.     IF data # 0L THEN
  291.       WriteString ('    Length of Data: ');
  292.       WriteString (StrConv.CardToStr(data, 0));
  293.     END;
  294.     IF verbose THEN writeLn END;
  295.   END ReportCodeLen;
  296.  
  297. PROCEDURE WriteOutHeader (VAR f: File; prgname, sfx, msg: ARRAY OF CHAR);
  298.   VAR st, sd: String;
  299.   BEGIN
  300.     ConcatName (prgname, sfx, sd);
  301.     Create (f, sd, writeSeqTxt, replaceOld);
  302.     
  303.     Report (3, 'Writing symbol file: '); WriteString (sd); WriteString ('...');
  304.     
  305.     (* Titel und Datum in Datei schreiben *)
  306.     Text.WriteString (f, linkerTitle);
  307.     DateToText (CurrentDate (), '', sd);
  308.     TimeToText (CurrentTime (), '', st);
  309.     Text.WriteString (f, Strings.Space (
  310.                   76 - (LENGTH(sd) + 2 + LENGTH(st) + LENGTH(linkerTitle)) ));
  311.     Text.WriteString (f, sd);
  312.     Text.WriteString (f, '  ');
  313.     Text.WriteString (f, st);
  314.     Text.WriteLn (f);
  315.     Text.WriteLn (f);
  316.   END WriteOutHeader;
  317.  
  318. PROCEDURE OutputSymbols (REF arg, prgname: ARRAY OF CHAR; mod: ModList): BOOLEAN;
  319.   (*
  320.    * Ausgabe der Symbole. Z.Zt. sind dies nur Modul- und Prozedurnamen.
  321.    *
  322.    * 'arg': Eventuell weiterer Text, der hinter der Option '-S' angegeben ist.
  323.    * 'prgname': Name der vom Linker erzeugten Code-Datei.
  324.    * 'mod': Liste d. Module/Symbole. Struktur siehe Def-Text.
  325.    * RETURN: FALSE, wenn Datei nicht erzeugt werden konnte.
  326.    *)
  327.  
  328.   PROCEDURE ofs (n: LONGCARD): LONGCARD;
  329.     (* entfernt MSB von 'n' *)
  330.     BEGIN
  331.       RETURN n MOD $1000000
  332.     END ofs;
  333.  
  334.   PROCEDURE seg (n: LONGCARD): CARDINAL;
  335.     (* liefert MSB von 'n' *)
  336.     BEGIN
  337.       RETURN SHORT (n DIV $1000000)
  338.     END seg;
  339.  
  340.   VAR f: File; m: ModList; p: SymbolList; sd, st: String;
  341.   
  342.   BEGIN
  343.     (* Erzeuge Datei mit Name/Pfad wie Ausgabedabei, jedoch mit Endung "M2S" *)
  344.     WriteOutHeader (f, prgname, 'M2S', 'Writing symbol file: ');
  345.     
  346.     Text.WriteString (f, "FORMAT: 1");
  347.     Text.WriteLn (f);
  348.     Text.WriteLn (f);
  349.     Text.WriteString (f, "PROGRAM: ");
  350.     Text.WriteString (f, prgname);
  351.     Text.WriteLn (f);
  352.     WHILE mod # NIL DO
  353.       WITH mod^ DO
  354.         Text.WriteLn (f);
  355.         Text.WriteString (f, "MODULE: ");
  356.         Text.WriteString (f, name);
  357.         Text.WriteString (f, "  (");
  358.         Text.WriteString (f, codeName);
  359.         Text.Write (f, ")");
  360.         Text.WriteLn (f);
  361.         IF codeLen = 0 THEN
  362.           Text.WriteString (f, "  Removed.");
  363.           Text.WriteLn (f);
  364.         ELSE
  365.           Text.WriteString (f, "  Head: ");
  366.           NumberIO.WriteLHex (f, codeAdr, 7);
  367.           Text.WriteString (f, "  Var: ");
  368.           NumberIO.WriteLHex (f, varAdr, 7);
  369.           Text.WriteLn (f);
  370.           p:= symbolRoot;
  371.           WHILE p # NIL DO
  372.             IF ofs (p^.addr) = $FFFFFF THEN
  373.               (* Prozedur wurde durchs Optimieren entfernt *)
  374.               (* ... *)
  375.             ELSE
  376.               Text.WriteString (f, "  ");
  377.               IF seg (p^.addr) # 0 THEN
  378.                 HALT (* Kein Code- sondern BSS- oder DATA-Segment. Anzeigen! *)
  379.               END;
  380.               NumberIO.WriteLHex (f, ofs (p^.addr), 7);
  381.               Text.WriteString (f, "  ");
  382.               Text.WriteString (f, p^.name);
  383.               Text.WriteLn (f);
  384.             END;
  385.             p:= p^.next
  386.           END;
  387.         END
  388.       END;
  389.       mod:= mod^.next
  390.     END;
  391.     Close (f);
  392.     IF State (f) < 0 THEN
  393.       ReportIOError (State (f));
  394.       RETURN FALSE
  395.     END;
  396.     WriteString ('OK.');
  397.     RETURN TRUE
  398.   END OutputSymbols;
  399.  
  400.  
  401. PROCEDURE BeginWriting;
  402.   (* Start des Erzeugens der Ausgabedatei *)
  403.   BEGIN
  404.     IF verbose THEN
  405.       writeLn;
  406.       WriteString ('Writing linked file...');
  407.       writeLn
  408.     ELSE
  409.       gotoXY (0,ProtLine); delLine; WriteString ('Writing linked file');
  410.     END
  411.   END BeginWriting;
  412.  
  413. PROCEDURE WritingOut (modNo: CARDINAL);
  414.   (* Schreiben von Modul 'modNo' in die Ausgabedatei *)
  415.   BEGIN
  416.     IF verbose THEN
  417.       WriteString (Mod^[modNo].modname);
  418.       writeLn
  419.     ELSE
  420.       write ('.')
  421.     END
  422.   END WritingOut;
  423.  
  424. PROCEDURE EndWriting;
  425.   (* Ende des Erzeugens der Ausgabedatei *)
  426.   BEGIN
  427.     WriteString (' OK');
  428.     IF verbose THEN writeLn END
  429.   END EndWriting;
  430.  
  431. PROCEDURE InitOutput (maxmods: CARDINAL; REF title: ARRAY OF CHAR);
  432.   (* Erste aufgerufene Prozedur vom Linker. Dient zum Öffnen des Windows.
  433.    * 'maxmods': Max. Anzahl zu linkender Modul (hiernach wird Window-Größe
  434.    * bestimmt); 'title': Titel und Version des Linkers.
  435.    *)
  436.   
  437.   PROCEDURE cardmax (a,b:CARDINAL): CARDINAL;
  438.     BEGIN
  439.       IF a > b THEN RETURN a ELSE RETURN b END;
  440.     END cardmax;
  441.  
  442.   VAR ok: BOOLEAN;
  443.  
  444.   BEGIN
  445.     Strings.Assign (title, linkerTitle, ok);
  446.     Open (stdOut,
  447.       cardmax (80, (maxmods+Columns+MAX(LLRange)-2) DIV Columns * NameWidth),
  448.       21, WQualitySet{movable,dynamic,titled}, noHideWdw, forceCursor,
  449.       title, -1,-1,-1,-1, ok);
  450.     IF ok THEN
  451.       ALLOCATE (Mod, TSIZE (modNameDesc) * LONG (maxmods));
  452.     END;
  453.     IF Mod = NIL THEN
  454.       TermProcess (MOSGlobals.OutOfMemory)
  455.     END
  456.   END InitOutput;
  457.  
  458. PROCEDURE VerboseOutput;
  459.   (* Aufruf nach 'InitOutput', wenn '-V' in Cmdline f. Linker übergeben *)
  460.   BEGIN
  461.     verbose:= TRUE
  462.       (* Achtung: die 'verbose'-Auswertungen sind noch nicht vollständig! *)
  463.   END VerboseOutput;
  464.  
  465. PROCEDURE OutputInitList (REF arg, prgname: ARRAY OF CHAR;
  466.                           init: ARRAY OF CARDINAL;
  467.                           highIdx, firstIdx: CARDINAL): BOOLEAN;
  468.   
  469.   VAR f: File; idx: CARDINAL;
  470.   
  471.   PROCEDURE wrMod (i: CARDINAL);
  472.     BEGIN
  473.       WITH Mod^[init[i]] DO
  474.         Text.WriteString (f, modname);
  475.         Text.WriteLn (f);
  476.       END;
  477.     END wrMod;
  478.   
  479.   BEGIN
  480.     (* Erzeuge Datei mit Name/Pfad wie Ausgabedabei, jedoch mit Endung "M2I" *)
  481.     WriteOutHeader (f, prgname, 'M2I', 'Writing init-list file: ');
  482.     wrMod (firstIdx);
  483.     FOR idx:= 1 TO highIdx DO
  484.       IF idx # firstIdx THEN wrMod (idx) END;
  485.     END;
  486.     Close (f);
  487.     IF State (f) < 0 THEN
  488.       ReportIOError (State (f));
  489.       RETURN FALSE
  490.     END;
  491.     WriteString ('OK.');
  492.     RETURN TRUE
  493.   END OutputInitList;
  494.  
  495. BEGIN
  496.   Mod:= NIL;
  497.   highMod:= 0;
  498.   verbose:= FALSE;
  499.   anotherMain:= FALSE
  500. END MM2LnkIO.
  501.